﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Globalization;
using System.Windows.Forms;
using WindowsFormsAero;

namespace BGShell.Forms
{
    internal sealed partial class AboutForm : AeroForm
    {
        private Font _headerFontBold;

        private StringFormat _headerFormat;

        public AboutForm()
        {
            InitializeComponent();

            lblProduct.Text = ProductName;

            ApplyLabelFormat(lblVersion, BGShellApplicationInfo.FileVersion.FileVersion);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.Clear(Color.White);
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

            PaintHeader(e);

            using (var brush = CreateContentBackgroundBrush())
            {
                e.Graphics.FillRectangle(brush, ContentRectangle);
            }

            base.OnPaint(e);
        }

        private void PaintHeader(PaintEventArgs e)
        {
            using (var headerBrush = CreateHeaderBackgroundBrush())
            {
                e.Graphics.FillRectangle(headerBrush, HeaderRectangle);
            }

            e.Graphics.DrawIcon(ResourcesNative.BGShellIcon, IconRectangle);

            if (_headerFontBold == null)
            {
                _headerFontBold = CreateHeaderFont(true);
            }

            if (_headerFormat == null)
            {
                _headerFormat = new StringFormat()
                {
                    LineAlignment = StringAlignment.Center,
                };
            }

            e.Graphics.DrawString("BGShell", _headerFontBold, Brushes.White, HeaderTextRectangle, _headerFormat);
        }

        protected override void OnClosed(System.EventArgs e)
        {
            if (_headerFontBold != null)
            {
                _headerFontBold.Dispose();
                _headerFontBold = null;
            }

            base.OnClosed(e);
        }

        private Font CreateHeaderFont(bool bold)
        {
            FontFamily trebuchet = null;
            FontFamily arial = null;

            foreach (var family in FontFamily.Families)
            {
                if (family.Name == "Corbel")
                {
                    return CreateHeaderFont(family, bold);
                }

                if (family.Name == "Trebuchet MS")
                {
                    trebuchet = family;
                    continue;
                }

                if (family.Name == "Arial")
                {
                    arial = family;
                    continue;
                }
            }

            if (trebuchet != null)
            {
                return CreateHeaderFont(trebuchet, bold);
            }

            if (arial != null)
            {
                return CreateHeaderFont(arial, bold);
            }

            return CreateHeaderFont(FontFamily.GenericSansSerif, bold);
        }

        private Font CreateHeaderFont(FontFamily family, Boolean bold)
        {
            return new Font(family, HeaderFontPxSize, bold ? FontStyle.Bold : FontStyle.Regular, GraphicsUnit.Pixel);
        }

        private Rectangle IconRectangle
        {
            get { return new Rectangle(new Point(Padding.Left, Padding.Top), ResourcesNative.BGShellIcon.Size); }
        }

        private Rectangle HeaderRectangle
        {
            get { return new Rectangle(0, 0, ClientRectangle.Width, IconRectangle.Height + Padding.Vertical); }
        }

        private Rectangle HeaderTextRectangle
        {
            get 
            {
                var rect = HeaderRectangle;
                
                rect.X += (Padding.Horizontal + IconRectangle.Width);
                rect.Width -= (Padding.Horizontal + IconRectangle.Width);
                
                rect.Y += (int)(Padding.Top * 0.9);
                rect.Height -= (int)(Padding.Top * 0.9) + Padding.Bottom;

                return rect;
            }
        }

        private Rectangle ContentRectangle
        {
            get
            {
                var y = HeaderRectangle.Bottom + 1;
                return new Rectangle(0, y, ClientRectangle.Width, ClientRectangle.Height - y);
            }
        }

        private int HeaderFontPxSize
        {
            get { return (int)(HeaderTextRectangle.Height * 0.65); }
        }

        private Brush CreateContentBackgroundBrush()
        {
            return new LinearGradientBrush(ContentRectangle, Color.Black, Color.Black, 90f, false)
            {
                InterpolationColors = new ColorBlend(4)
                {
                    Positions = new float[] { 0.0f, 0.038f, 0.5f, 1.0f },
                    Colors = new Color[]
                    {
                        Color.FromArgb(130, 174, 224),
                        Color.FromArgb(223, 234, 245),
                        Color.FromArgb(255, 255, 255),
                        Color.FromArgb(197, 224, 244),
                    },
                }
            };
        }

        private Brush CreateHeaderBackgroundBrush()
        {
            var dark = Color.FromArgb(12, 85, 147);
            var light = Color.FromArgb(81, 149, 203);

            return new LinearGradientBrush(HeaderRectangle, dark, light, 0f, false)
            {
                Blend = new Blend(5)
                {
                    Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 1.0f },
                    Factors = new float[]   { 0.0f, 0.4f, 0.5f, 0.3f, 1.0f } 
                }
            };
        }

        private void lnkCopyright_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start(ThisAssembly.UrlPeople);
        }

        private void lnkLicense_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start(ThisAssembly.UrlLicense);
        }

        private static void ApplyLabelFormat(Label lbl, params object[] args)
        {
            lbl.Text = String.Format(CultureInfo.CurrentUICulture, lbl.Text, args);
        }
    }
}
